<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>文件传输测试</title>
    <link rel="stylesheet" href="css/websocket-test.css">
</head>
<body>
    <div class="container">
        <h1>文件传输测试</h1>
        <div class="notification notification-info">
            此页面用于测试WebSocket文件传输功能，支持大文件分块传输
        </div>

        <div class="row">
            <div class="col">
                <div class="card">
                    <h2 class="card-header">连接设置</h2>
                    <div class="form-group">
                        <label for="endpoint">WebSocket端点</label>
                        <input type="text" id="endpoint" value="/ChatMessageServer" placeholder="例如 /ChatMessageServer">
                    </div>
                    <div class="form-group">
                        <label for="username">您的用户名</label>
                        <input type="text" id="username" placeholder="输入用户名">
                    </div>
                    <div class="form-group">
                        <label for="receiver">接收者</label>
                        <input type="text" id="receiver" placeholder="输入接收者用户名">
                    </div>
                    <div class="form-group">
                        <button id="connectBtn" class="btn">连接</button>
                        <button id="disconnectBtn" class="btn btn-secondary" disabled>断开</button>
                    </div>
                    <div class="d-flex align-items-center mt-2">
                        <div id="statusIndicator" class="status-indicator status-offline"></div>
                        <span id="statusText">未连接</span>
                    </div>
                </div>
            </div>
            
            <div class="col">
                <div class="card">
                    <h2 class="card-header">连接配置</h2>
                    <div class="form-group">
                        <label for="chunkSize">分块大小 (字节)</label>
                        <select id="chunkSize">
                            <option value="524288">512 KB</option>
                            <option value="1048576" selected>1 MB</option>
                            <option value="2097152">2 MB</option>
                            <option value="5242880">5 MB</option>
                            <option value="10485760">10 MB</option>
                        </select>
                    </div>
                    <div class="form-group">
                        <label for="transferMode">传输模式</label>
                        <select id="transferMode">
                            <option value="standard">标准模式</option>
                            <option value="chunks" selected>分块模式</option>
                        </select>
                    </div>
                </div>
            </div>
        </div>
        
        <div class="row">
            <div class="col">
                <div class="card" id="uploadCard">
                    <h2 class="card-header">上传文件</h2>
                    <div class="form-group">
                        <label for="fileInput">选择文件</label>
                        <input type="file" id="fileInput" multiple>
                    </div>
                    <div id="selectedFileList" class="mt-2"></div>
                    <div class="form-group">
                        <button id="sendFileBtn" class="btn" disabled>发送文件</button>
                        <button id="cancelBtn" class="btn btn-secondary" disabled>取消</button>
                    </div>
                </div>
                
                <div class="card mt-3">
                    <h2 class="card-header">传输进度</h2>
                    <div id="transferStatusContainer"></div>
                </div>
            </div>
            
            <div class="col">
                <div class="card">
                    <h2 class="card-header">已接收的文件</h2>
                    <div id="receivedFilesContainer" class="message-list" style="height: 300px;">
                        <div class="text-center text-muted p-5">尚未收到任何文件</div>
                    </div>
                </div>
            </div>
        </div>
        
        <div class="row">
            <div class="col">
                <div class="card">
                    <h2 class="card-header d-flex justify-content-between align-items-center">
                        <span>传输日志</span>
                        <button id="clearLogsBtn" class="btn btn-small btn-secondary">清空日志</button>
                    </h2>
                    <div id="logContainer" class="message-list" style="height: 200px;"></div>
                </div>
            </div>
        </div>
    </div>

    <!-- 脚本引入 -->
    <script src="js/websocket-client.js"></script>
    <script>
    // DOM元素
    const connectBtn = document.getElementById('connectBtn');
    const disconnectBtn = document.getElementById('disconnectBtn');
    const endpointInput = document.getElementById('endpoint');
    const usernameInput = document.getElementById('username');
    const receiverInput = document.getElementById('receiver');
    const statusIndicator = document.getElementById('statusIndicator');
    const statusText = document.getElementById('statusText');
    const fileInput = document.getElementById('fileInput');
    const selectedFileList = document.getElementById('selectedFileList');
    const sendFileBtn = document.getElementById('sendFileBtn');
    const cancelBtn = document.getElementById('cancelBtn');
    const chunkSizeSelect = document.getElementById('chunkSize');
    const transferModeSelect = document.getElementById('transferMode');
    const transferStatusContainer = document.getElementById('transferStatusContainer');
    const receivedFilesContainer = document.getElementById('receivedFilesContainer');
    const logContainer = document.getElementById('logContainer');
    const clearLogsBtn = document.getElementById('clearLogsBtn');

    // 变量
    let wsClient = null;
    let selectedFiles = [];
    let activeTransfers = {};
    let receivedFileChunks = {};

    // 页面初始化
    function init() {
        // 从URL参数获取用户名和端点
        const urlParams = new URLSearchParams(window.location.search);
        if (urlParams.has('username')) {
            usernameInput.value = urlParams.get('username');
        }
        if (urlParams.has('endpoint')) {
            endpointInput.value = urlParams.get('endpoint');
        }
        if (urlParams.has('receiver')) {
            receiverInput.value = urlParams.get('receiver');
        }

        // 绑定事件
        connectBtn.addEventListener('click', connect);
        disconnectBtn.addEventListener('click', disconnect);
        fileInput.addEventListener('change', handleFileSelect);
        sendFileBtn.addEventListener('click', sendFiles);
        cancelBtn.addEventListener('click', cancelTransfers);
        clearLogsBtn.addEventListener('click', clearLogs);
    }

    // 连接WebSocket
    function connect() {
        const endpoint = endpointInput.value.trim();
        const username = usernameInput.value.trim();

        if (!endpoint) {
            addLog('错误', 'WebSocket端点不能为空');
            return;
        }

        if (!username) {
            addLog('错误', '用户名不能为空');
            return;
        }

        // 禁用连接按钮
        connectBtn.disabled = true;
        addLog('信息', `尝试连接到 ${endpoint}...`);

        try {
            // 创建WebSocket客户端
            wsClient = new WebSocketClient(endpoint, username, {
                onConnect: handleConnect,
                onDisconnect: handleDisconnect,
                onMessage: handleMessage,
                onError: handleError,
                onReconnect: handleReconnect,
                onReconnectFailed: handleReconnectFailed
            });

            // 连接
            wsClient.connect();
        } catch (error) {
            addLog('错误', `连接初始化失败: ${error.message}`);
            connectBtn.disabled = false;
        }
    }

    // 处理连接成功
    function handleConnect() {
        // 更新UI状态
        statusIndicator.className = 'status-indicator status-online';
        statusText.textContent = '已连接';
        connectBtn.disabled = true;
        disconnectBtn.disabled = false;
        updateSendButtonState();
        
        addLog('成功', '连接已建立');
    }

    // 处理连接断开
    function handleDisconnect(event) {
        // 更新UI状态
        statusIndicator.className = 'status-indicator status-offline';
        statusText.textContent = '已断开';
        connectBtn.disabled = false;
        disconnectBtn.disabled = true;
        sendFileBtn.disabled = true;
        cancelBtn.disabled = true;

        addLog('信息', `连接已断开${event.code ? (' (代码: ' + event.code + ')') : ''}`);
    }

    // 处理接收消息
    function handleMessage(message) {
        addLog('接收', JSON.stringify(message).substring(0, 100) + '...');
        
        if (message.type === 'media_transfer') {
            handleFileChunk(message);
        } else if (message.type === 'file_transfer_complete') {
            handleFileTransferComplete(message);
        } else if (message.type === 'chat' && message.contentType === 'file') {
            handleDirectFileReceived(message);
        } else if (message.type === 'error') {
            addLog('错误', message.content || '接收到错误消息');
        }
    }

    // 处理收到的文件分块
    function handleFileChunk(message) {
        const { messageId, chunkIndex, totalChunks, fileName, content } = message;
        
        if (!receivedFileChunks[messageId]) {
            // 初始化新文件的接收状态
            receivedFileChunks[messageId] = {
                chunks: Array(totalChunks).fill(null),
                totalChunks: totalChunks,
                receivedChunks: 0,
                fileName: fileName,
                startTime: Date.now()
            };
            
            // 创建进度显示
            createReceivedFileProgressUI(messageId, fileName, totalChunks);
        }
        
        // 保存分块
        receivedFileChunks[messageId].chunks[chunkIndex] = content;
        receivedFileChunks[messageId].receivedChunks++;
        
        // 更新进度
        updateReceivedFileProgress(messageId);
        
        // 检查是否所有分块都已接收
        if (receivedFileChunks[messageId].receivedChunks === totalChunks) {
            completeFileReception(messageId);
        }
    }

    // 完成文件接收
    function completeFileReception(messageId) {
        const fileInfo = receivedFileChunks[messageId];
        addLog('成功', `文件 ${fileInfo.fileName} 的所有分块已接收，正在组合...`);
        
        // 组合所有分块
        let base64Data = '';
        for (const chunk of fileInfo.chunks) {
            if (chunk) base64Data += chunk;
        }
        
        // 创建下载链接
        displayReceivedFile(messageId, fileInfo.fileName, base64Data);
        
        // 发送完成确认消息
        if (wsClient) {
            wsClient.send({
                type: 'file_transfer_complete',
                fromUser: wsClient.username,
                toUser: fileInfo.fromUser,
                relatedMessageId: messageId,
                content: 'received'
            });
        }
    }

    // 处理文件传输完成消息
    function handleFileTransferComplete(message) {
        const transferId = message.relatedMessageId;
        
        if (activeTransfers[transferId]) {
            addLog('成功', `文件 ${activeTransfers[transferId].fileName} 已成功传输到 ${message.fromUser}`);
            
            // 更新传输状态UI
            const statusElem = document.getElementById(`transfer-${transferId}`);
            if (statusElem) {
                statusElem.querySelector('.progress-bar-fill').style.width = '100%';
                statusElem.querySelector('.transfer-status').textContent = '完成';
                statusElem.querySelector('.transfer-status').className = 'transfer-status text-success';
            }
            
            // 从活动传输中移除
            delete activeTransfers[transferId];
        }
    }

    // 处理直接接收的文件（非分块）
    function handleDirectFileReceived(message) {
        const { fromUser, content, fileName } = message;
        
        addLog('接收', `从 ${fromUser} 接收到文件 ${fileName || 'file'}`);
        
        // 显示文件
        const fileId = 'file_' + Date.now();
        displayReceivedFile(fileId, fileName, content);
    }

    // 处理错误
    function handleError(error) {
        addLog('错误', error.message || '发生未知错误');
    }

    // 处理重连尝试
    function handleReconnect(attempt, maxAttempts) {
        statusText.textContent = `正在重连 (${attempt}/${maxAttempts})`;
        statusText.className = 'animate-blink';
        addLog('信息', `尝试重连 (${attempt}/${maxAttempts})...`);
    }

    // 处理重连失败
    function handleReconnectFailed() {
        statusText.textContent = '重连失败';
        statusText.className = '';
        connectBtn.disabled = false;
        addLog('错误', '重连失败，已达到最大尝试次数');
    }

    // 主动断开连接
    function disconnect() {
        if (wsClient) {
            wsClient.disconnect();
        }
    }

    // 处理文件选择
    function handleFileSelect(e) {
        const files = e.target.files;
        if (!files || files.length === 0) return;
        
        // 将文件添加到列表
        selectedFiles = Array.from(files);
        updateFileList();
        updateSendButtonState();
    }

    // 更新文件列表显示
    function updateFileList() {
        selectedFileList.innerHTML = '';
        
        if (selectedFiles.length === 0) {
            selectedFileList.innerHTML = '<div class="text-muted">未选择文件</div>';
            return;
        }
        
        const list = document.createElement('ul');
        list.style.listStyle = 'none';
        list.style.padding = '0';
        
        selectedFiles.forEach((file, index) => {
            const item = document.createElement('li');
            
            // 格式化文件大小
            const sizeInKB = Math.round(file.size / 1024);
            const sizeInMB = (file.size / (1024 * 1024)).toFixed(2);
            const sizeStr = sizeInKB < 1024 ? `${sizeInKB} KB` : `${sizeInMB} MB`;
            
            item.innerHTML = `
                <div class="d-flex align-items-center justify-content-between mb-2">
                    <div>
                        <strong>${file.name}</strong>
                        <div class="text-muted">${file.type || '未知类型'} - ${sizeStr}</div>
                    </div>
                    <button class="btn btn-small btn-secondary remove-file" data-index="${index}">移除</button>
                </div>
            `;
            list.appendChild(item);
        });
        
        selectedFileList.appendChild(list);
        
        // 添加移除按钮事件
        document.querySelectorAll('.remove-file').forEach(btn => {
            btn.addEventListener('click', (e) => {
                const index = parseInt(e.target.getAttribute('data-index'));
                selectedFiles.splice(index, 1);
                updateFileList();
                updateSendButtonState();
            });
        });
    }

    // 更新发送按钮状态
    function updateSendButtonState() {
        sendFileBtn.disabled = !wsClient || !wsClient.connected || selectedFiles.length === 0 || !receiverInput.value.trim();
        cancelBtn.disabled = Object.keys(activeTransfers).length === 0;
    }

    // 发送文件
    async function sendFiles() {
        const receiver = receiverInput.value.trim();
        
        if (!receiver) {
            addLog('错误', '请输入接收者用户名');
            return;
        }
        
        if (!wsClient || !wsClient.connected) {
            addLog('错误', '未连接到WebSocket服务器');
            return;
        }
        
        if (selectedFiles.length === 0) {
            addLog('错误', '请选择要发送的文件');
            return;
        }
        
        // 禁用发送按钮
        sendFileBtn.disabled = true;
        
        // 获取配置
        const chunkSize = parseInt(chunkSizeSelect.value);
        const useChunks = transferModeSelect.value === 'chunks';
        
        // 逐个发送文件
        for (const file of selectedFiles) {
            // 检查文件大小
            if (file.size > 100 * 1024 * 1024) { // 超过100MB
                addLog('警告', `文件 ${file.name} 超过100MB，可能会导致传输问题`);
            }
            
            try {
                if (useChunks || file.size > 1024 * 1024) { // 使用分块模式或文件大于1MB
                    await sendFileInChunks(file, receiver, chunkSize);
                } else {
                    await sendFileDirectly(file, receiver);
                }
            } catch (error) {
                addLog('错误', `发送文件 ${file.name} 时出错: ${error.message}`);
            }
        }
        
        // 重置文件选择
        fileInput.value = '';
        selectedFiles = [];
        updateFileList();
        updateSendButtonState();
    }

    // 直接发送文件（不分块）
    async function sendFileDirectly(file, receiver) {
        addLog('信息', `准备发送文件: ${file.name}`);
        
        try {
            const data = await FileUtil.readFileAsBase64(file);
            
            // 获取文件扩展名
            let fileExtension = '';
            const fileNameParts = file.name.split('.');
            if (fileNameParts.length > 1) {
                fileExtension = '.' + fileNameParts.pop();
            }
            
            // 发送文件
            wsClient.sendMediaMessage(
                receiver,
                'file',
                data,
                file.name,
                fileExtension,
                file.size
            );
            
            addLog('发送', `已发送文件: ${file.name}`);
        } catch (error) {
            throw new Error(`读取文件失败: ${error.message}`);
        }
    }

    // 分块发送文件
    async function sendFileInChunks(file, receiver, chunkSize) {
        addLog('信息', `准备分块发送文件: ${file.name}`);
        
        try {
            // 获取文件扩展名
            let fileExtension = '';
            const fileNameParts = file.name.split('.');
            if (fileNameParts.length > 1) {
                fileExtension = '.' + fileNameParts.pop();
            }
            
            // 分割文件
            const chunks = await FileUtil.splitFileIntoChunks(file, chunkSize);
            addLog('信息', `文件已分为 ${chunks.length} 个块`);
            
            // 创建传输ID
            const transferId = wsClient.generateUUID();
            
            // 记录传输信息
            activeTransfers[transferId] = {
                fileName: file.name,
                fileSize: file.size,
                totalChunks: chunks.length,
                sentChunks: 0,
                startTime: Date.now()
            };
            
            // 创建传输进度UI
            createTransferStatusUI(transferId, file.name, chunks.length);
            
            // 启用取消按钮
            cancelBtn.disabled = false;
            
            // 发送每个分块
            for (let i = 0; i < chunks.length; i++) {
                if (!activeTransfers[transferId]) {
                    // 传输已被取消
                    addLog('信息', `传输已取消: ${file.name}`);
                    throw new Error('传输已取消');
                }
                
                // 发送分块
                wsClient.send({
                    type: 'media_transfer',
                    fromUser: wsClient.username,
                    toUser: receiver,
                    contentType: 'file',
                    messageId: transferId,
                    chunkIndex: i,
                    totalChunks: chunks.length,
                    content: chunks[i],
                    fileName: file.name,
                    fileExtension: fileExtension,
                    fileSize: file.size
                });
                
                // 更新发送进度
                activeTransfers[transferId].sentChunks++;
                updateTransferProgress(transferId);
                
                // 为了避免过载服务器，在每个块之间添加小延迟
                if (i < chunks.length - 1) {
                    await new Promise(resolve => setTimeout(resolve, 10));
                }
            }
            
            addLog('成功', `文件 ${file.name} 的所有块已发送，等待接收方确认...`);
            
        } catch (error) {
            if (error.message !== '传输已取消') {
                throw error;
            }
        }
    }

    // 取消所有传输
    function cancelTransfers() {
        Object.keys(activeTransfers).forEach(transferId => {
            const transfer = activeTransfers[transferId];
            addLog('信息', `取消传输: ${transfer.fileName}`);
            
            // 更新UI
            const statusElem = document.getElementById(`transfer-${transferId}`);
            if (statusElem) {
                statusElem.querySelector('.transfer-status').textContent = '已取消';
                statusElem.querySelector('.transfer-status').className = 'transfer-status text-danger';
            }
            
            delete activeTransfers[transferId];
        });
        
        updateSendButtonState();
    }

    // 创建传输状态UI
    function createTransferStatusUI(transferId, fileName, totalChunks) {
        const statusItem = document.createElement('div');
        statusItem.id = `transfer-${transferId}`;
        statusItem.className = 'transfer-item card mb-2';
        statusItem.style.padding = '10px';
        
        statusItem.innerHTML = `
            <div class="d-flex justify-content-between">
                <div>
                    <strong>${fileName}</strong>
                    <div class="text-muted">发送中 - 0/${totalChunks} 块</div>
                </div>
                <div class="transfer-status">发送中</div>
            </div>
            <div class="progress-bar mt-2">
                <div class="progress-bar-fill" style="width: 0%"></div>
            </div>
        `;
        
        transferStatusContainer.appendChild(statusItem);
    }

    // 更新传输进度
    function updateTransferProgress(transferId) {
        const transfer = activeTransfers[transferId];
        if (!transfer) return;
        
        const statusElem = document.getElementById(`transfer-${transferId}`);
        if (!statusElem) return;
        
        const progress = Math.round((transfer.sentChunks / transfer.totalChunks) * 100);
        statusElem.querySelector('.progress-bar-fill').style.width = progress + '%';
        statusElem.querySelector('.text-muted').textContent = `发送中 - ${transfer.sentChunks}/${transfer.totalChunks} 块`;
        
        // 计算传输速度
        const elapsedTime = (Date.now() - transfer.startTime) / 1000; // 秒
        if (elapsedTime > 0) {
            const bytesPerSecond = (transfer.sentChunks / transfer.totalChunks) * transfer.fileSize / elapsedTime;
            const speed = formatTransferSpeed(bytesPerSecond);
            statusElem.querySelector('.transfer-status').textContent = speed;
        }
    }

    // 创建接收文件进度UI
    function createReceivedFileProgressUI(fileId, fileName, totalChunks) {
        const progressItem = document.createElement('div');
        progressItem.id = `receive-${fileId}`;
        progressItem.className = 'transfer-item card mb-2';
        progressItem.style.padding = '10px';
        
        progressItem.innerHTML = `
            <div class="d-flex justify-content-between">
                <div>
                    <strong>${fileName}</strong>
                    <div class="text-muted">接收中 - 0/${totalChunks} 块</div>
                </div>
                <div class="transfer-status">接收中</div>
            </div>
            <div class="progress-bar mt-2">
                <div class="progress-bar-fill" style="width: 0%"></div>
            </div>
        `;
        
        transferStatusContainer.appendChild(progressItem);
        return progressItem;
    }

    // 更新接收文件进度
    function updateReceivedFileProgress(fileId) {
        const fileInfo = receivedFileChunks[fileId];
        if (!fileInfo) return;
        
        const progressElem = document.getElementById(`receive-${fileId}`);
        if (!progressElem) return;
        
        const progress = Math.round((fileInfo.receivedChunks / fileInfo.totalChunks) * 100);
        progressElem.querySelector('.progress-bar-fill').style.width = progress + '%';
        progressElem.querySelector('.text-muted').textContent = `接收中 - ${fileInfo.receivedChunks}/${fileInfo.totalChunks} 块`;
        
        // 计算接收速度
        const elapsedTime = (Date.now() - fileInfo.startTime) / 1000; // 秒
        if (elapsedTime > 0) {
            // 这里假设每个块大小相同，实际上可能需要更准确的计算
            const bytesReceived = fileInfo.receivedChunks * (fileInfo.chunks[0] ? fileInfo.chunks[0].length * 0.75 : 0); // 粗略估计，base64编码效率约为0.75
            const bytesPerSecond = bytesReceived / elapsedTime;
            const speed = formatTransferSpeed(bytesPerSecond);
            progressElem.querySelector('.transfer-status').textContent = speed;
        }
    }

    // 显示接收到的文件
    function displayReceivedFile(fileId, fileName, base64Data) {
        // 更新进度UI
        const progressElem = document.getElementById(`receive-${fileId}`);
        if (progressElem) {
            progressElem.querySelector('.progress-bar-fill').style.width = '100%';
            progressElem.querySelector('.transfer-status').textContent = '完成';
            progressElem.querySelector('.transfer-status').className = 'transfer-status text-success';
        }
        
        // 清除"没有文件"提示
        if (receivedFilesContainer.querySelector('.text-center.text-muted')) {
            receivedFilesContainer.innerHTML = '';
        }
        
        // 创建文件显示项
        const fileItem = document.createElement('div');
        fileItem.className = 'message-item animate-fade-in';
        
        // 获取文件扩展名和类型
        const fileExt = fileName.split('.').pop().toLowerCase();
        let fileType = 'unknown';
        let fileIcon = '📄';
        
        switch (fileExt) {
            case 'jpg':
            case 'jpeg':
            case 'png':
            case 'gif':
                fileType = 'image';
                fileIcon = '🖼️';
                break;
            case 'doc':
            case 'docx':
                fileType = 'document';
                fileIcon = '📝';
                break;
            case 'xls':
            case 'xlsx':
                fileType = 'spreadsheet';
                fileIcon = '📊';
                break;
            case 'pdf':
                fileType = 'pdf';
                fileIcon = '📑';
                break;
            case 'zip':
            case 'rar':
                fileType = 'archive';
                fileIcon = '🗜️';
                break;
            case 'mp3':
            case 'wav':
                fileType = 'audio';
                fileIcon = '🔊';
                break;
            case 'mp4':
            case 'avi':
                fileType = 'video';
                fileIcon = '🎥';
                break;
        }
        
        // 创建下载链接
        const dataUrl = base64Data.startsWith('data:') ? base64Data : `data:application/octet-stream;base64,${base64Data}`;
        const timeStr = new Date().toLocaleTimeString();
        
        fileItem.innerHTML = `
            <div class="message-header">
                <span class="message-sender">${fileIcon} ${fileName}</span>
                <span class="message-time">${timeStr}</span>
            </div>
            <div class="mt-2">
                <a href="${dataUrl}" download="${fileName}" class="btn btn-small">下载文件</a>
                ${fileType === 'image' ? `<button class="btn btn-small btn-secondary preview-btn" data-url="${dataUrl}">预览</button>` : ''}
            </div>
        `;
        
        receivedFilesContainer.appendChild(fileItem);
        
        // 添加预览按钮事件
        if (fileType === 'image') {
            const previewBtn = fileItem.querySelector('.preview-btn');
            previewBtn.addEventListener('click', () => {
                showImagePreview(dataUrl, fileName);
            });
        }
    }

    // 显示图片预览
    function showImagePreview(dataUrl, fileName) {
        // 创建模态框
        const modal = document.createElement('div');
        modal.style.position = 'fixed';
        modal.style.top = '0';
        modal.style.left = '0';
        modal.style.width = '100%';
        modal.style.height = '100%';
        modal.style.backgroundColor = 'rgba(0,0,0,0.8)';
        modal.style.zIndex = '1000';
        modal.style.display = 'flex';
        modal.style.justifyContent = 'center';
        modal.style.alignItems = 'center';
        modal.style.flexDirection = 'column';
        
        const img = document.createElement('img');
        img.src = dataUrl;
        img.style.maxWidth = '90%';
        img.style.maxHeight = '80%';
        img.style.objectFit = 'contain';
        img.style.border = '2px solid white';
        
        const caption = document.createElement('div');
        caption.textContent = fileName;
        caption.style.color = 'white';
        caption.style.marginTop = '10px';
        caption.style.fontSize = '16px';
        
        modal.appendChild(img);
        modal.appendChild(caption);
        
        // 点击关闭
        modal.addEventListener('click', () => {
            document.body.removeChild(modal);
        });
        
        document.body.appendChild(modal);
    }

    // 格式化传输速度
    function formatTransferSpeed(bytesPerSecond) {
        if (bytesPerSecond < 1024) {
            return Math.round(bytesPerSecond) + ' B/s';
        } else if (bytesPerSecond < 1024 * 1024) {
            return Math.round(bytesPerSecond / 1024 * 10) / 10 + ' KB/s';
        } else {
            return Math.round(bytesPerSecond / (1024 * 1024) * 10) / 10 + ' MB/s';
        }
    }

    // 添加日志
    function addLog(level, message) {
        const logItem = document.createElement('div');
        logItem.className = 'message-item animate-fade-in';
        
        const timeStr = new Date().toLocaleTimeString();
        let levelClass = '';
        
        switch (level.toLowerCase()) {
            case '错误':
                levelClass = 'text-danger';
                break;
            case '成功':
                levelClass = 'text-success';
                break;
            case '信息':
                levelClass = 'text-muted';
                break;
            case '警告':
                levelClass = 'text-warning';
                break;
            case '接收':
                levelClass = 'text-info';
                break;
            case '发送':
                levelClass = 'text-primary';
                break;
            default:
                levelClass = '';
        }
        
        logItem.innerHTML = `
            <div class="message-header">
                <span class="message-sender ${levelClass}">[${level}]</span>
                <span class="message-time">${timeStr}</span>
            </div>
            <div class="message-content">${message}</div>
        `;
        
        logContainer.appendChild(logItem);
        logContainer.scrollTop = logContainer.scrollHeight;
    }

    // 清空日志
    function clearLogs() {
        logContainer.innerHTML = '';
    }

    // 初始化页面
    document.addEventListener('DOMContentLoaded', init);
    </script>
</body>
</html> 